package com.harmontronics.hanma.paas.paas.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.harmontronics.hanma.paas.paas.common.PageBase;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmCarbonCopy;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmProcess;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmTask;
import com.harmontronics.hanma.paas.paas.domain.app.service.HmProcessRuntimeService;
import com.harmontronics.hanma.paas.paas.domain.app.service.TransUserIdFunction;
import com.harmontronics.hanma.paas.paas.domain.iam.entity.GroupMemberUser;
import com.harmontronics.hanma.paas.paas.domain.iam.service.HmUserGroupMemberService;
import com.harmontronics.hanma.paas.paas.domain.organization.entity.HmUser;
import com.harmontronics.hanma.paas.paas.domain.organization.entity.SubmitterUser;
import com.harmontronics.hanma.paas.paas.domain.organization.service.HmUserService;
import com.harmontronics.hanma.paas.paas.domain.organization.service.IHmUserService;
import com.harmontronics.hanma.paas.paas.token.ComposeTokenKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ldb
 */
@Service("hmProcessRuntimeAppService")
@DS("#header.App-Unique")
public class HmProcessRuntimeAppService extends HmProcessRuntimeService {

    @Autowired
    private IHmUserService hmUserService;

    @Autowired
    private ComposeTokenKit composeTokenKit;

    @Autowired
    private HmUserGroupMemberService hmUserGroupMemberService;
    TransUserIdFunction function = (sourceId -> {
        if (sourceId.startsWith("u_")) {
            return CollUtil.toList(Long.parseLong(sourceId.split("_")[1]));
        }
        if (sourceId.startsWith("o_")) {
            Long orgId = Long.parseLong(sourceId.split("_")[1]);
            List<HmUser> hmUserList = hmUserService.findByManageOrg(orgId);
            return hmUserList.stream().map(HmUser::getId).collect(Collectors.toList());
        }

        if (sourceId.startsWith("ug_")) {
            Long userGroupOd = Long.parseLong(sourceId.split("_")[1]);
            List<GroupMemberUser> members = hmUserGroupMemberService.selectGroupMemberWithGroupId(userGroupOd);
            List<Long> userIds = members.stream().filter(e -> e.getIsOrg() == 0).map(GroupMemberUser::getUnionId).collect(Collectors.toList());
            List<Long> orgIds = members.stream().filter(e -> e.getIsOrg() == 1).map(GroupMemberUser::getUnionId).collect(Collectors.toList());
            for (Long orgId : orgIds) {
                List<HmUser> hmUserList = hmUserService.findByManageOrg(orgId);
                userIds.addAll(hmUserList.stream().map(HmUser::getId).collect(Collectors.toList()));
            }
            return userIds;
        }

        throw new IllegalArgumentException(sourceId);
    });


    public PageBase<HmTask> listToDo(Long processId, int pageNo, int pageSize) {
        Long userId = composeTokenKit.getId();

        List<String> assigneeList = getAssignee(userId);
        PageBase<HmTask> pageBase = super.listToDo(processId, assigneeList,pageNo, pageSize);
        return fillHmTaskPageBase(pageBase);
    }

    private List<String> getAssignee(Long userId) {
        List<String> assigneeList = new ArrayList<>();
        assigneeList.add("u_" + userId);
        HmUser hmUser = hmUserService.get(userId);
        if (StringUtils.hasLength(hmUser.getManageOrg())) {
            int length = hmUser.getManageOrg().length();
            String trimmedStr = hmUser.getManageOrg().substring(1,length - 1);
            String[] orgIdStrs = trimmedStr.split("]\\[");
            Arrays.stream(orgIdStrs).forEach(o->assigneeList.add("o_"+o));
        }
        List<Long> userGroupIds = hmUserGroupMemberService.selectGroupWithUserId(userId);
        userGroupIds.forEach(e->assigneeList.add("ug_"+e.toString()));
        return assigneeList;
    }

    public void completeTask(Long processId,String processInstanceId,String taskId, String message, Map<String, Object> values, List<HmCarbonCopy> carbonCopys,String modelKey,String serviceKey) throws SQLException, IOException {

        super.completeTask(processId,processInstanceId,taskId, message, values, carbonCopys, modelKey,serviceKey,function);
    }


    public List<HmProcess> getOnGoingProcess() {
        Long userId = composeTokenKit.getId();

        List<String> assigneeList = getAssignee(userId);
        return super.getOnGoingProcess(assigneeList);
    }
    @Override
    public PageBase<HmTask> listMyStartProcessToDo(Long processId, int pageNo, int pageSize) {
        PageBase<HmTask> pageBase = super.listMyStartProcessToDo(processId, pageNo, pageSize);
        return fillHmTaskPageBase(pageBase);
    }

    public PageBase<HmTask> fillHmTaskPageBase(PageBase<HmTask> pageBase) {
        if (pageBase.isEmpty()) {
            return pageBase;
        }
        Map<String, List<HmTask>> groupedTaskMap = pageBase.getData().stream().collect(Collectors.groupingBy(HmTask::getSubmitterId));

        for (Map.Entry<String, List<HmTask>> entry : groupedTaskMap.entrySet()) {
            List<Long> userIds = function.doTrans(entry.getKey());
            List<SubmitterUser> submitterUsers = hmUserService.selectSubmitterUserIn(userIds);
            StringJoiner userIdJoiner = new StringJoiner(",");
            StringJoiner nameJoiner = new StringJoiner(",");
            StringJoiner orgIdJoiner = new StringJoiner(",");
            StringJoiner orgNameJoiner = new StringJoiner(",");
            for (SubmitterUser submitterUser : submitterUsers) {
                userIdJoiner.add(submitterUser.getSubmitterId().toString());
                nameJoiner.add(submitterUser.getSubmitterName());
                orgIdJoiner.add(submitterUser.getMainOrgId().toString());
                orgNameJoiner.add(submitterUser.getMainOrgName());
            }
            for (HmTask hmTask : entry.getValue()) {
                hmTask.setSubmitterId(userIdJoiner.toString());
                hmTask.setSubmitterName(nameJoiner.toString());
                hmTask.setSubmitterOrgId(orgIdJoiner.toString());
                hmTask.setSubmitterOrgName(orgNameJoiner.toString());
            }
        }

        return pageBase;
    }
}
